﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Schema;
using System.IO;
using System.Reflection;
using System.Configuration;
using System.Diagnostics;
using System.Xml.Serialization;
using Microsoft.XmlDiffPatch;


namespace WebServicesTesting.Automation
{
    public class UnitTest
    {
        
        private TestContext TestContextInstance;

        public TestContext TestContext
        {
            get
            {
                return TestContextInstance;
            }
            set
            {
                TestContextInstance = value;
            }
        }

        //This helper class method takes two string as inputs and compare them 

        public void CompareString(int condition, string ArrgetAgeExpected, string getAgeActual)
        {


            int result = getAgeActual.Trim().CompareTo(ArrgetAgeExpected.Trim().ToString());

            Assert.AreEqual(0, result, 0, "Expected String:" + ArrgetAgeExpected.Trim().ToString() + " doesn't match with Actual String: " + getAgeActual);
           
        }

        //This helper class method takes two string Arrays as inputs and compare them 
        public void CompareString(int condition, string[] ArrgetAgeExpected, string[] ArrgetAgeActual)
        {

            for (int i = 0; i < ArrgetAgeExpected.Length; i++)
            {

                int result = ArrgetAgeActual[i].CompareTo(ArrgetAgeExpected[i].Trim().ToString());

                if (result != 0)
                {
                    Assert.AreEqual(0, result, 0, "Expected String Array doesn't match with Actual String Array");
                    break;
                }
            }
         }

        //This helper class method takes string and string arrays as inputs and compare them 

        public void CompareString(int condition, string[] ArrgetAgeExpected, string getAgeActual)
        {
       

            int result = getAgeActual.Trim().CompareTo(ArrgetAgeExpected[0].Trim().ToString());

            Assert.AreEqual(0, result, 0, "Expected String Array doesn't match with Actual String");
            
        }

        //This helper class compares Dictionary with string array
        public void CompareDictionaryWithExpectedArray(Dictionary<int, string> ActualDic, string[,] ArrgetAgeExpected)
        {

            for (int i = 0; i < (ArrgetAgeExpected.Length) / 2 - 1; i++)
            {
                foreach (KeyValuePair<int, string> pair in ActualDic)
                {

                    string strKey = pair.Key.ToString();
                    int strComKey = string.Compare(ArrgetAgeExpected[i, 0], strKey);
                    int strComValue = string.Compare(ArrgetAgeExpected[i, 1], pair.Value);

                    if (strComKey == 0)
                    {
                        if (strComValue == 0)
                        {
                            Assert.AreEqual(0, strComKey, 0, "Expected dictionary key doesnt match with Actual dictionary key");
                            Assert.AreEqual(0, strComValue, 0, "Expected dictionary value doesn't match with Actual dictionary key");
                            
                            break;

                        }
                    }
                }
            }
        }
           
        //This helper class validates that database insertion is done as result of Web service call by validating it against the database
        public void Verify_DbInsert(string ConnString, string Query, string expected)
        {

            DataTable dt = GetDataTable(ConnString, Query);
            string str = null;
            //converting table to string to verify with the expected string
            foreach (DataRow rows in dt.Rows)
            {
                foreach (DataColumn cols in dt.Columns)
                {
                    str = str + rows[cols].ToString().Trim() + ",";
                }

            }

            str = str.Substring(0, (str.Length - 1));

            Assert.AreEqual(expected, str, "Expected does not match actual");

        }

        //This helper class validates that database update is done as result of Web service call by validating it against the database
        public void Verify_DBUpdate(string ConnString, string Query, string expected)
        {

            DataTable dt = GetDataTable(ConnString, Query);
            //  int row = 0, col = 0;
            string str = null;
            //converting table to string to verify with the expected string
            foreach (DataRow rows in dt.Rows)
            {
                foreach (DataColumn cols in dt.Columns)
                {
                    str = str + rows[cols].ToString().Trim() + ", ";
                }

            }
            str = str.Substring(0, (str.Length - 2));
            Assert.AreEqual(expected, str, "Expected does not match actual");


        }

        //This helper class validates that database deletion is done as result of Web service call by validating it against the database
        public void Verify_DBDelete(string ConnString, string Query)
        {


            DataTable dt = GetDataTable(ConnString, Query);
            int count = dt.Rows.Count;
            Assert.AreEqual(0, count, "Record not deleted from DB");

        }

        //This helper class verifies two dataset and validate them
        public void Verify_Dataset(string ConnString, string Query, DataSet dst)
        {

            //actual dataset
            DataTable dt = GetDataTable(ConnString, Query);
            //expected dataset
            DataTable dt1 = dst.Tables[0];

            for (int i = 0; i < dt.Rows.Count; i++)
            {

                var array1 = dt.Rows[i].ItemArray;
                var array2 = dt1.Rows[i].ItemArray;

                if (array1.SequenceEqual(array2))
                {

                }
                else
                {
                    Assert.Fail("Dataset does not match" + "expected-" + array2.ToString() + " Actual-" + array1.ToString());
                }

            }

        }

        //This helper class verifies schema of a web service method by validating it agianst its XSD
        public bool Verify_Schema(string targetNameSpace, string xsdPath,string requestXml)
        {
            bool value = false;
            try
            {
                //creating setting for the xml reader
                XmlReaderSettings settings = new XmlReaderSettings();

                settings.ValidationType = ValidationType.Schema;
                 
                settings.Schemas.Add(targetNameSpace, xsdPath);

                settings.ValidationEventHandler += new ValidationEventHandler(ValidationEventHandler);
                XmlDocument resXmldoc = new XmlDocument();
                resXmldoc.LoadXml(requestXml);
                //creates a temp xml which is to be validated by the xsd
                resXmldoc.Save("C:\\Windows\\Temp\\temp.xml");

                XmlReader reader = XmlReader.Create("C:\\Windows\\Temp\\temp.xml", settings);

                System.Xml.XPath.XPathDocument doc = new XPathDocument(reader);

                XPathNavigator navigator = doc.CreateNavigator();
                if (Errormsg.Global != null)
                {
                    value = false;
                }
                else
                {
                    value = true;
                }

                reader.Close();
                //deletes the temp xml
                File.Delete("C:\\Windows\\Temp\\temp.xml");
                return value;
            }
                catch(XmlSchemaValidationException exe)
            {
                string str = exe.Message;
                return value = false;
            }

            catch (Exception ex)
            {
                string e= ex.Message.ToString();
                return value = false;
                
              
            }
        }

        //This helper class uses reflection to verify the web method signature (input parameters, return list)
        public void Verify_methodPrototype(object myObject, string Methodname, string paramlist, string returnTypelist)
        {

            string s = "";
            bool parambool = false;
            bool retrnbool = false;
            MethodInfo methods = myObject.GetType().GetMethod(Methodname);
            if (methods.Equals(null))
            {
                Assert.Fail("Method does mot exist");
            }
            else
            {

                ParameterInfo[] param = methods.GetParameters();
                string returnType = methods.ReturnType.ToString();
                foreach (var p in param)
                {
                    s = s + p.ParameterType.FullName;
                }
                string expected = paramlist.Replace(",", "");
                if (expected.Equals(s))
                {
                    parambool = true;
                }
                else
                {
                    parambool = false;
                }
                if (returnType.Equals(returnTypelist))
                {
                    retrnbool = true;
                }
                else
                {
                    retrnbool = false;
                }
                if (parambool.Equals(false) && retrnbool.Equals(false))
                {
                    Assert.Fail("Parametr && Return Type does not match");
                }
                if (parambool.Equals(false))
                {
                    Assert.Fail("Parametr does not match");
                }

                if (retrnbool.Equals(false))
                {
                    Assert.Fail("Return Type does not match");
                }


            }
        }

        //This helper class verifies if the web service method exist
        public bool Verify_MethodExistence(object myObject, List<string> list)
        {
            bool flag = true;
            string s = null;
            try
            {
                //gets all the methods of the webservice
                MethodInfo[] methods = myObject.GetType().GetMethods();
                bool iterationFlag = false;
                foreach (var methodName in list)
                {
                    foreach (var method in methods)
                    {
                        if (methodName == method.Name)
                        {

                            iterationFlag = true;
                            break;
                        }
                        else
                        {
                            iterationFlag = false;
                        }

                    }

                    if (!iterationFlag)
                    {
                        flag = false;
                    }

                }
                return flag;
            }
            catch (Exception e)
            {
                string str = e.Message.ToString();
                return flag = false;
            }

        }

        //This helper class verifies web service method results in a new file creation at a given path
        public void Verify_FileCreation(string FilePath)
        {

            if (File.Exists(FilePath))
            {

            }

            else
            {
                Assert.Fail("File does not exist");
            }


        }

        //This helper method verifies if the row count matches       
        public void Verify_RowCountDataSet(int expected, int actual)
        {
            Assert.AreEqual(expected, actual);

        }

        public List<T> DTO_PopulateObject<T>(object DTOObject, object myObj)
        {
            Type DTOType = DTOObject.GetType();
            List<T> ListOfDTOs = new List<T>();
            PropertyInfo[] pi = myObj.GetType().GetProperties();
            PropertyInfo[] p = DTOObject.GetType().GetProperties();
            foreach (PropertyInfo k in pi)
            {
                PropertyInfo mem = myObj.GetType().GetProperty(k.Name);
                PropertyInfo mem1 = DTOObject.GetType().GetProperty(k.Name);
                if (mem1.GetValue(DTOObject, null) != null)
                {
                    mem.SetValue(myObj, mem1.GetValue(DTOObject, null).ToString().Trim(), null);
                }
                else
                {
                    mem.SetValue(myObj, DBNull.Value.ToString(), null);
                }

            }
            ListOfDTOs.Add((T)myObj);
            return ListOfDTOs;
        }

        public List<T> DTO_PopulateDBResults<T>(DataTable dt) where T : class
        {
            List<T> ListOfDTOs = new List<T>();
            int row = dt.Rows.Count;
            int col = dt.Columns.Count;
            string[] str = new string[col];
            int c = 0;
            foreach (DataColumn dc in dt.Columns)
            {
                str[c++] = dc.ToString();

            }
            for (int i = 0; i < row; i++)
            {
                T dtoObject = Activator.CreateInstance<T>();

                DataRow dataRow = dt.Rows[i];
                
                for (int j = 0; j < col; j++)
                {

                    PropertyInfo mem = dtoObject.GetType().GetProperty(str[j]);
                    mem.SetValue(dtoObject,dataRow[j].ToString().Trim(), null);
                     
                }

                ListOfDTOs.Add(dtoObject);
            }
            return ListOfDTOs;
        }

        public bool DTO_XmlComparison(Object ExpectedDTOList, Object ActualDTOList, Type ObjectType)
        {
            StackTrace stackTrace = new StackTrace();

            // get calling method name
            string method = stackTrace.GetFrame(1).GetMethod().Name;

            XmlSerializer serializer = new XmlSerializer(ObjectType);
            StreamWriter textWriter = new StreamWriter("C:\\TestResults\\" + method + "expected" + ".xml");

            serializer.Serialize(textWriter, ExpectedDTOList);
            textWriter.Close();
            XmlSerializer serializer1 = new XmlSerializer(ObjectType);
            StreamWriter textWriter1 = new StreamWriter("C:\\TestResults\\" + method + "actual" + ".xml");

            serializer1.Serialize(textWriter1, ActualDTOList);
            textWriter1.Close();
            XmlDiff xmldiff = new XmlDiff();
            bool bXMLmatch = xmldiff.Compare("C:\\TestResults\\" + method + "expected" + ".xml", "C:\\TestResults\\" + method + "actual" + ".xml", false);
            Assert.AreEqual(true, bXMLmatch, "Expected does not match actual");
            return bXMLmatch;
        }
        
        // ---------------------------------- UTILITIES------------------------------------------------------------------------------  

        private static void ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs arg)
        {
            Errormsg.Global = arg.Message.ToString();

        }

        public class Errormsg
        {

            public static string Global = null;

        }

        //To get the result in the form of DataSet from query
        public DataSet ConvertQueryToDataset(string ConnectionString, string query)
          {

            SqlConnection conn1 = new SqlConnection(ConnectionString);
            string sql = @query;

            conn1.Open();
            SqlDataAdapter da = new SqlDataAdapter(sql, conn1);
            DataSet ds = new DataSet();
            da.Fill(ds);
            conn1.Close();

            return ds;
            

         }
                       
        //Convert dataset in to string where Column = 0
        public string[] ConvertDataSetToString(int condition, DataSet ds)
            {
                if (condition == 1)
                {
                    string[] stringArray = new string[ds.Tables[0].Columns.Count];

                    for (int row = 0; row < ds.Tables[0].Rows.Count; ++row)
                    {
                        stringArray[row] = ds.Tables[0].Rows[row][0].ToString();
                    }

                    return stringArray;
                }
                else if (condition == 2)
                {
                    string[] stringArray = new string[ds.Tables[0].Columns.Count];


                    for (int row = 0; row < ds.Tables[0].Rows.Count; ++row)
                    {
                        for (int col = 0; col < ds.Tables[0].Columns.Count; col++)
                        {
                            stringArray[col] = ds.Tables[0].Rows[row][col].ToString();
                        }
                    }

                    return stringArray;
                }

                else if (condition == 3)
                {
                    string[] stringArray = new string[ds.Tables[0].Rows.Count];


                    for (int row = 0; row < ds.Tables[0].Rows.Count; ++row)
                    {
                        for (int col = 0; col < ds.Tables[0].Columns.Count; col++)
                        {
                            stringArray[row] = ds.Tables[0].Rows[row][col].ToString();
                        }
                    }

                    return stringArray;
                }

                else
                {
                    return null;
                }

            }

        //Convert dataset in to string where Column is 1 but multiple rows
        public string[,] ConvertDataSetToStringForCol(DataSet ds)
            {
                string[,] stringArray = new string[ds.Tables[0].Rows.Count, ds.Tables[0].Columns.Count];


                for (int row = 0; row < ds.Tables[0].Rows.Count; ++row)
                {
                    for (int col = 0; col < ds.Tables[0].Columns.Count; col++)
                    {
                        stringArray[row, col] = ds.Tables[0].Rows[row][col].ToString();
                    }
                }

                return stringArray;


            }

        public static bool Verify_Results(object[] objWCF, SqlDataReader objDB)
        {
            bool testResult = true;
            string columnName = string.Empty;
            foreach (Object pair in objWCF)
            {
                try
                {
                    objDB.Read();
                }
                catch (Exception ex)
                {
                    testResult = false;
                    return testResult;
                }
                System.Reflection.PropertyInfo[] pinfo = pair.GetType().GetProperties();
                string DB_Value;
                string Services_Value;
                for (int count = 0; count < objDB.FieldCount; count++)
                {
                    try
                    {
                        columnName = pinfo[count + 1].Name;
                        Services_Value = pinfo[count + 1].GetValue(pair, null).ToString();
                    }
                    catch (NullReferenceException nx)
                    {
                        Services_Value = "";
                    }

                    DB_Value = objDB[columnName].ToString();

                    if ((DB_Value == null) && (Services_Value == null))
                    {
                        //Assert.AreEqual(DB_Value, Services_Value, pinfo[count + 1].Name + " property value is not equal ");
                    }
                    else
                    {
                        testResult = false;
                        return testResult;
                    }
                }
            }

            return testResult;
        }

        public void Verify_Results_Obj(SqlDataReader db_results, object[] srvc_results, TestContext testcontext)
        {
            foreach (Object pair in srvc_results)
            {
                db_results.Read();
                System.Reflection.PropertyInfo[] pinfo = pair.GetType().GetProperties();
                string DB_Value;
                string Services_Value;
                for (int count = 0; count < db_results.FieldCount; count++)
                {
                    DB_Value = db_results[count].ToString();
                    try
                    {
                        Services_Value = pinfo[count + 1].GetValue(pair, null).ToString();
                    }
                    catch (NullReferenceException nx)
                    {
                        Services_Value = "";
                    }

                    if ((DB_Value == null) && (Services_Value == null))
                    {
                        //Assert.AreEqual(DB_Value, Services_Value, pinfo[count + 1].Name + " property value is not equal ");
                    }
                    else
                    {
                        try { Assert.AreEqual(DB_Value, Services_Value, pinfo[count + 1].Name + " property value is not equal "); }
                        catch { }

                        testcontext.WriteLine(DB_Value + " :database value," + Services_Value + " :Services value " + " for property " + pinfo[count + 1].Name);
                    }

                }
                testcontext.WriteLine("*********************Iteration ended ****************************");
            }
        }

        public void Verify_Results_Dict(SqlDataReader db_results, Dictionary<int, string> srvc_results, TestContext testcontext)
        {
            int db_count = 0;
            try
            {
                foreach (var pair in srvc_results)
                {
                    db_results.Read();
                    Assert.AreEqual(db_results[0], pair.Key, db_results.GetName(0) + " value does not matches");
                    testcontext.WriteLine(db_results[0] + " :database value," + pair.Key + " :Services value " + " for property " + db_results.GetName(0));
                    Assert.AreEqual(db_results[1], pair.Value, db_results.GetName(1) + "  does not matches");
                    testcontext.WriteLine(db_results[0] + " :database value," + pair.Value + " :Services value " + " for property " + db_results.GetName(1));
                    db_count = db_count + 1;
                }
            }
            catch { testcontext.WriteLine("Error occured during the result verification"); }

            while (db_results.Read())
            {
                db_count++;
            }

            if (db_count == srvc_results.Count)
            {

            }
            else
            {
                testcontext.WriteLine("The record counts for the datareader as well as service does not match, Db count is " + db_count + " and services count is " + srvc_results.Count);
                Assert.Fail("The record counts for the datareader as well as service does not match, Db count is " + db_count + " and services count is " + srvc_results.Count);

            }

        }

        public void Verify_Results_Dict_Long(SqlDataReader db_results, Dictionary<long, string> srvc_results, TestContext testcontext)
        {
            int db_count = 0;
            try
            {
                foreach (var pair in srvc_results)
                {
                    db_results.Read();
                    Assert.AreEqual(db_results[0], pair.Key, db_results.GetName(0) + " value does not matches");
                    testcontext.WriteLine(db_results[0] + " :database value," + pair.Key + " :Services value " + " for property " + db_results.GetName(0));
                    Assert.AreEqual(db_results[1], pair.Value, db_results.GetName(1) + "  does not matches");
                    testcontext.WriteLine(db_results[0] + " :database value," + pair.Value + " :Services value " + " for property " + db_results.GetName(1));
                    db_count = db_count + 1;
                    testcontext.WriteLine("****************************************End of Iteration*****************************************************");
                }
            }
            catch { testcontext.WriteLine("Error occured during the result verification"); }

            while (db_results.Read())
            {
                db_count++;
            }

            if (db_count == srvc_results.Count)
            {

            }
            else
            {
                testcontext.WriteLine("The record counts for the datareader as well as service does not match, Db count is " + db_count + " and services count is " + srvc_results.Count);
                Assert.Fail("The record counts for the datareader as well as service does not match, Db count is " + db_count + " and services count is " + srvc_results.Count);

            }

            testcontext.WriteLine("****************************************End of Verification for *****************************************************");

        }

        public void Verify_Results_String(SqlDataReader db_results, string srvc_results, TestContext testcontext)
        {
            try
            {
                db_results.Read();
                Assert.AreEqual(db_results[0], srvc_results, "Value does not matches");
                testcontext.WriteLine(db_results[0] + " :database value," + srvc_results + " :Services value " + "");


            }
            catch { testcontext.WriteLine("Error occured during the result verification"); }

        }

        public void Verify_Results_Dict_String(SqlDataReader db_results, Dictionary<string, string> srvc_results, TestContext testcontext)
        {
            int db_count;
            db_count = 0;
            try
            {
                foreach (var pair in srvc_results)
                {
                    db_results.Read();
                    Assert.AreEqual(db_results[0], pair.Key, db_results.GetName(0) + " value does not matches");
                    testcontext.WriteLine(db_results[0] + " :database value," + pair.Key + " :Services value " + " for property " + db_results.GetName(0));
                    Assert.AreEqual(db_results[1], pair.Value, db_results.GetName(1) + "  does not matches");
                    testcontext.WriteLine(db_results[0] + " :database value," + pair.Value + " :Services value " + " for property " + db_results.GetName(1));
                    db_count = db_count + 1;
                }
            }
            catch { testcontext.WriteLine("Error occured during the result verification"); }

            while (db_results.Read())
            {
                db_count++;
            }

            if (db_count == srvc_results.Count)
            {

            }
            else
            {
                testcontext.WriteLine("The record counts for the datareader as well as service does not match, Db count is " + db_count + " and services count is " + srvc_results.Count);
                Assert.Fail("The record counts for the datareader as well as service does not match, Db count is " + db_count + " and services count is " + srvc_results.Count);

            }
        }

        public int? Verify_Null(string str)
        {
            if (str == "")
            {
                return null;
            }
            else
            {
                return Convert.ToInt32(str);
            }
        }

        public DateTime? Verify_Null_DT(string str)
        {
            if (str == "")
            {
                return null;
            }
            else
            {
                return Convert.ToDateTime(str);
            }
        }

        public string Verify_Null_String(string str)
        {
            if (str == "")
            {
                return null;
            }
            else
            {
                return (str);
            }
        }

        public DataTable GetDataTable(string ConnString, string Query)
        {
            string connString = ConnString;
            string sql = Query;
            SqlConnection conn = new SqlConnection(connString);
            conn.Open();
            SqlDataAdapter da = new SqlDataAdapter(sql, conn);
            DataSet ds = new DataSet();
            da.Fill(ds);
            DataTable dt = ds.Tables[0];
            conn.Close();
            return dt;
        }


        }
    }

